package com.glsc.ngateway.flowable.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.glsc.ngateway.common.api.flowable.dto.FlowableCopyDto;
import com.glsc.ngateway.common.base.converter.flowable.FlowableCopyConverter;
import com.glsc.ngateway.common.base.domain.mysql.flowable.ActHiComment;
import com.glsc.ngateway.common.base.domain.mysql.flowable.FlowableCopy;
import com.glsc.ngateway.common.base.domain.mysql.flowable.FlowableEhrEmp;
import com.glsc.ngateway.common.api.flowable.dto.param.ParamCopyDto;
import com.glsc.ngateway.common.base.repo.mysql.flowable.FlowableCopyRepo;
import org.apache.logging.log4j.util.Strings;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class FlowableCopyService {

    private static final Logger logger = LoggerFactory.getLogger(FlowableCopyService.class);

    @Autowired
    FlowableCopyRepo flowableCopyRepo;
    @Autowired
    FlowableEhrEmpService flowableEhrEmpService;

    @Autowired
    FlowableCommonService flowableCommonService;

    @Autowired
    private TaskService taskService;

    /**
     * 给用户增加流程的抄送，支持多次抄送
     * * *
     */
    @Transactional(rollbackFor = Exception.class)
    public void addCopy(ParamCopyDto param, HistoricProcessInstance pi) throws UnsupportedEncodingException {
        logger.info("准备抄送流程：{}-{}", param, pi);
        String[] userDestList = param.getUsernameDestination().split(",");
        String userNameSource = flowableEhrEmpService.getChineseName(param.getUsernameSource());
        String startUserName = flowableEhrEmpService.getChineseName(pi.getStartUserId());
        for (String s : userDestList) {
            FlowableCopy fc = new FlowableCopy();
            fc.setSysid(param.getSysid());
            fc.setUsernameDestinationChinese(flowableEhrEmpService.getChineseName(s));
            fc.setUsernameDestination(s);
            fc.setUsernameSourceChinese(userNameSource);
            fc.setUsernameSource(param.getUsernameSource());
            fc.setProcessInstanceId(pi.getId());
            fc.setProcessDefinitionKey(pi.getProcessDefinitionKey());
            fc.setStartTime(LocalDateTime.now());
            fc.setStartUser(pi.getStartUserId());
            fc.setStartUserName(startUserName);
            fc.setTitle(pi.getName());
            fc.setRemark(param.getRemark());
            //待阅状态
            fc.setStatus("0");
            flowableCopyRepo.save(fc);
            logger.info("增加抄送信息：{}", fc);
        }
        List<String> copyToList = Arrays.stream(param.getUsernameDestination().split(",")).collect(Collectors.toList());
        List<FlowableEhrEmp> userInfos = flowableEhrEmpService.findAllByBadgeIn(copyToList);
        //增加转发任务备注
        StringBuilder commentStr = new StringBuilder(String.format("【抄送】抄送流程给%s", CollectionUtil.isNotEmpty(userInfos) ?
                userInfos.stream().map(FlowableEhrEmp::getName).collect(Collectors.joining(",")) : param.getUsernameDestination()));
        if (StrUtil.isNotBlank(param.getRemark())) {
            commentStr.append("，备注：").append(param.getRemark());
        }
        if(param.isAddComment()) {
            //taskid为空则新加历史节点,并且直接向comment表中插入数据
            if (Strings.isBlank(param.getTaskId())) {
                String taskId = "CopyTask-" + UUID.randomUUID();
                flowableCommonService.addNewHiTask(pi.getProcessDefinitionId(), param.getProcessId(), param.getUsernameDestination(), taskId, param.getTaskName(), param.getSysid());
                ActHiComment comment = new ActHiComment();
                comment.setId("CopyTaskComment" + UUID.randomUUID());
                comment.setType("comment");
                comment.setTime(LocalDateTime.now());
                comment.setUserId(param.getUsernameSource());
                comment.setTaskId(taskId);
                comment.setProcInstId(param.getProcessId());
                comment.setAction("AddComment");
                comment.setMessage(commentStr.toString());
                comment.setFullMsg(comment.getMessage().getBytes(StandardCharsets.UTF_8));
                flowableCommonService.addComment(comment);
            } else {
                taskService.addComment(param.getTaskId(), param.getProcessId(), commentStr.toString());
            }
        }
    }

    public Page<FlowableCopyDto> getCopyProcessList(String title, String processDefinitionKey, String userId, String sysid, String status, String startUser, LocalDateTime beginDate, LocalDateTime endDate, Pageable pageable) {
        List<String> processDefinitionKeys = new ArrayList();
        if (StrUtil.isNotEmpty(processDefinitionKey)) {
            String[] arrs = processDefinitionKey.split(",");
            Collections.addAll(processDefinitionKeys, arrs);
            processDefinitionKeys = processDefinitionKeys.stream().filter(StrUtil::isNotEmpty).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(processDefinitionKeys)) {
            processDefinitionKeys = null;
        }
        Page<FlowableCopy> pageData = flowableCopyRepo.findByUsernameAndSysid(title, processDefinitionKeys, userId, sysid, status, startUser, beginDate, endDate, pageable);
        return new PageImpl<>(
                pageData.getContent()
                        .stream()
                        .map(FlowableCopyConverter::domain2Dto)
                        .collect(Collectors.toList())
                , pageData.getPageable(), pageData.getTotalPages());
    }

    /**
     * 更新抄送状态任务为已读状态，即待阅事件已经被处理
     *
     * @return
     */
    public void getCopyProcessDetail(String processId, String userId, String sysid) {
        logger.info("用户，已阅流程-{}-{}-{}", userId, processId, sysid);
        if (StrUtil.isEmpty(processId) || StrUtil.isEmpty(userId) || StrUtil.isEmpty(sysid)) {
            return;
        }

        List<FlowableCopy> userCopyList = flowableCopyRepo.findByProcessInstanceIdAndUsernameDestinationAndSysid(processId, userId, sysid);
        if (CollectionUtil.isEmpty(userCopyList)) {
            logger.warn("用户，流程，无抄送关系-{}-{}", userId, processId);
            return;
        }

        //查询用户流程抄送关系，对于待阅状态的更新为已阅状态
        List<FlowableCopy> updateCopyReadList = new ArrayList<>();
        for (FlowableCopy flowableCopy : userCopyList) {
            if ("0".equals(flowableCopy.getStatus())) {//待阅状态的
                flowableCopy.setStatus("1");//设置为已阅
                flowableCopy.setReadTime(LocalDateTime.now());//更新已阅时间
                updateCopyReadList.add(flowableCopy);
            }
        }
        if (CollectionUtil.isNotEmpty(updateCopyReadList)) {
            flowableCopyRepo.saveAll(updateCopyReadList);
        }
    }

    /**
     * 查询用户对某个流程的抄送记录
     * * *
     */
    public List<FlowableCopyDto> getCopyProcessOfUser(String processId, String userId, String sysid) {
        List<FlowableCopy> list = flowableCopyRepo.findByProcessInstanceIdAndUsernameDestinationAndSysid(processId, userId, sysid);

        return FlowableCopyConverter.domain2Dto(list);
    }

    public List<Map<String, String>> getUserParticipateProcessList(List<String> processIdList, String user, String sysId) {
        return flowableCopyRepo.findUserParticipateProcessList(processIdList, user, sysId);
    }

    public List<String>  getCopyUserList(List<String> processIdList) {
        return flowableCopyRepo.getCopyUserList(processIdList);
    }
}